package com.example.nio.tranport.mina.server;

import com.example.nio.tranport.mina.keepAlive.MinaKeepAliveMessageFactory;
import lombok.Data;
import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.service.IoHandler;
import org.apache.mina.core.service.IoService;
import org.apache.mina.core.service.IoServiceListener;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory;
import org.apache.mina.filter.keepalive.KeepAliveFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.util.Map;


/***
 * Mina的服务端
 */
@Data
public class MinaServer implements Server {

    Logger logger = LoggerFactory.getLogger(getClass());

    private int port;

    private IoHandler ioHandler;

    private IoAcceptor acceptor;

    private MinaKeepAliveMessageFactory keepAliveMessageFactory;

    private IoServiceListener ioServiceListener = new IoServiceListener() {

        @Override
        public void serviceActivated(IoService service) throws Exception {

        }

        @Override
        public void serviceIdle(IoService service, IdleStatus idleStatus) throws Exception {

        }

        @Override
        public void serviceDeactivated(IoService service) throws Exception {
            logger.warn("client 已掉线，服务端关闭");
        }

        @Override
        public void sessionCreated(IoSession session) throws Exception {
            logger.warn("client 会话连接完毕，会话id：" + session.getId());
        }

        @Override
        public void sessionClosed(IoSession session) throws Exception {
            logger.warn("client 会话关闭完毕，会话id：" + session.getId());
        }

        @Override
        public void sessionDestroyed(IoSession session) throws Exception {
            logger.warn("client 会话销毁完毕，会话id：" + session.getId());
        }
    };

    public MinaServer(int port, IoHandler ioHandler) {
        this.port = port;
        this.ioHandler = ioHandler;
        this.keepAliveMessageFactory = new MinaKeepAliveMessageFactory();
    }

    @Override
    public void init() throws Exception {

    }

    @Override
    public void start() throws Exception {
        try {
            this.acceptor = new NioSocketAcceptor();
            this.acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));
            this.acceptor.getFilterChain().addLast("heartbeat", new KeepAliveFilter(keepAliveMessageFactory));
            this.acceptor.setHandler(ioHandler);
            this.acceptor.addListener(ioServiceListener);
            this.acceptor.bind(new InetSocketAddress(port));
            logger.warn("server start at " + port);
        } catch (Exception e) {
            logger.warn("server start error :" + e.getMessage());
            if (this.acceptor != null) {
                this.acceptor.dispose();
            }
            throw new Exception("server start error :" + e.getMessage());
        }
    }

    @Override
    public void stop() throws Exception {
        if (this.acceptor != null) {
            this.acceptor.dispose();
        }
    }

    @Override
    public Map<Long, IoSession> getSessions() {
        return this.acceptor.getManagedSessions();
    }
}
